package com.tintintech.sendmail.protocol;

import java.net.ConnectException;
import java.util.List;
import java.util.Map;
//import java.util.concurrent.ArrayBlockingQueue;
//import java.util.concurrent.BlockingQueue;
//import java.util.concurrent.RejectedExecutionHandler;
//import java.util.concurrent.ThreadPoolExecutor;
//import java.util.concurrent.TimeUnit;
//import java.util.concurrent.BlockingQueue;
//import java.util.concurrent.LinkedBlockingQueue;
//import java.util.concurrent.ThreadPoolExecutor;
//import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import com.tintintech.sendmail.Config;
import com.tintintech.sendmail.helper.DNSHelper;
import com.tintintech.sendmail.helper.DataHelper;
import com.tintintech.sendmail.util.MailStat;
import com.tintintech.sendmail.util.MailBoxConstants;
import com.tintintech.sendmail.util.PrimaryKey;
import com.tintintech.sendmail.util.SmtpServer;

/* 发送邮件类 */
public final class MailService {
	
	
	public static final boolean send(Map<String, String> mailer)
	{
		String toemail = null;
		try 
		{
			toemail = mailer.get(MailBoxConstants.TO_EMAIL);
		}
		catch (NullPointerException npe)
		{
			npe.printStackTrace();
		}
		System.out.println("-send-");
		if (toemail == null)
		{
			return false;
		}
		List<String> ipList = DNSHelper.getTargetServerOfPriority(DNSHelper.getMxRecords(toemail));
		int size = ipList.size();
		if (size == 0)
		{
			return false;
		}
		String target = null;
		try {
			target = ipList.get(size - 1);
		} catch (Throwable tae) {
			System.out.println("IndexOutOfException");
			return false;
		}
		if (target == null)
		{
			return false;
		}
		SmtpServer server = new SmtpServer(target, toemail);//取优先级最高的
		if (server.getSocket().isConnected() == false)
		{
			return false;
		}
		try {
			SmtpCommand cmd = new SmtpCommand(server, new MimeMessage(mailer, Config.GLOBALS.get("charset")));
			MailStat.MAIL_SEND_NUM.incrementAndGet();
			if (cmd.sendMessage())
			{
				MailStat.MAIL_SEND_SUCCESS_NUM.incrementAndGet();
				return true;
			}
			else
			{
				return false;
			}
		} catch (ConnectException conne) {
			System.out.println("socket not connected!");
		} catch (Throwable tae) {
			System.out.println("send-exception");
		}
		
		return false;
	}	

	public final void run()
	{
        System.out.println("send mail worker thread start!");
        int num = new Integer(Config.GLOBALS.get("threadNum")).intValue(), i = 0;
        for (;i < num; i++)
        {
            Thread t = new Thread("SendmailThread_" + i){
                @Override
                public void run()
                {
                    while (MailService.getInstance().getRunning())
                    {
                    	try
                    	{
                    		MailStat.MAIL_DISCARD_NUM_1.incrementAndGet();
                    	    final Map<String, String> mailBox = DataHelper.MAILMAP_QUEUE.take();
                    	    MailStat.MAIL_DISCARD_NUM_2.incrementAndGet();
                            final String status = mailBox.get("status");
                            if (send(mailBox) == false)
                            {
                                if ("#1".equals(status))
                            	{
                                	final String json = DataHelper.JSON.encode(mailBox);
                                	DataHelper.SEND_FAILED_MAP.put(PrimaryKey.UUID() + "#1", json);
                                	MailStat.SEND_FAILED_NUM_1.incrementAndGet();
                            	}
                            	else
                            	{
                            		MailStat.setSendFailedItems(mailBox.get(MailBoxConstants.TO_EMAIL));
                                	MailStat.SEND_FAILED_NUM_2.incrementAndGet();                            		
                            	}
                            }
                            else
                            {
                                if ("#1".equals(status))
                                {
                                	MailStat.SEND_SUCCESS_NUM_1.incrementAndGet();
                                }
                                else
                                {
                                	MailStat.SEND_SUCCESS_NUM_2.incrementAndGet();                                	
                                }
                            }
                    	}
                    	catch (InterruptedException inupte)
                    	{
                    		System.out.println("thread-interrupt-exception");
                    		MailStat.SEND_FAILED_NUM_2.incrementAndGet();
                    		//当有线程挂起的时候，停止所有线程，在装箱操作的时候在启动所有线程
                    		MailService.getInstance().setRunning(false);
                    	}
                    	catch (Throwable e)
                    	{
                    		MailStat.SEND_FAILED_NUM_2.incrementAndGet();
                    		//全局捕获
                    		System.out.println("thread-exception");
                    		e.printStackTrace();
                    		MailService.getInstance().setRunning(false);
                    	}
                    }
                }
            };
            
            t.start();
        }		
	}
	
	
	public final void run1()
	{
		/*
		int maxThreadNum = new Integer(Config.GLOBALS.get("threadNum")).intValue();
		BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
		ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, maxThreadNum, 50, TimeUnit.MILLISECONDS, queue);
		
		while (true) {
			try {
				Map<String, String> mailBox = DataHelper.MAILMAP_QUEUE.take();
				threadPool.execute(new Thread(){
					public void run(){
						//handle box
						//final String status = mailBox.get("status");
					}
				});
			} catch (InterruptedException itpe) {
				
			} finally {
				
			}
		}
		*/
	}
	
	/**
	 * 应用多线程发信
	 */
	private AtomicBoolean running = new AtomicBoolean(false);
    public final void startWorker()
    {
        System.out.println("send mail worker thread start!");
        int num = new Integer(Config.GLOBALS.get("threadNum")).intValue(), i = 0;
        for (;i < num; i++)
        {
            Thread t = new Thread("SendmailThread_" + i){
                @Override
                public void run()
                {
                    String key, json;
                    Map<String, String> mailer;
                    while (MailService.getInstance().getRunning())
                    {
                    	try
                    	{
                    	    key = DataHelper.MAIL_QUEUE.take();
                    	    if (key  == null)
                            {
                                continue;
                            }
                            json = DataHelper.MAILBOX_MAP.get(key);
                            DataHelper.MAILBOX_MAP.remove(key);
                            if (json == null)
                            {
                            	if (key.lastIndexOf("#") == -1)
                            	{
                            		MailStat.MAIL_DISCARD_NUM_1.incrementAndGet();
                            	}
                            	else
                            	{
                            		MailStat.MAIL_DISCARD_NUM_2.incrementAndGet();
                            	}
                                continue;
                            }
                            
                            mailer = DataHelper.JSON.decodeForMap(json);
                            if (send(mailer) == false)
                            {
                                if (key.lastIndexOf("#") == -1)
                                {//对发送失败一次的邮件进行处理
                                	MailStat.SEND_FAILED_NUM_1.incrementAndGet();
                                    DataHelper.SEND_FAILED_MAP.put(key + "#1", json);
                                }
                                else
                                {
                                    //记录发送失败的邮件地址
                                	MailStat.setSendFailedItems(mailer.get(MailBoxConstants.TO_EMAIL));
                                	MailStat.SEND_FAILED_NUM_2.incrementAndGet();
                                }
                            }
                            else
                            {
                                if (key.lastIndexOf("#") == -1)
                                {
                                	MailStat.SEND_SUCCESS_NUM_1.incrementAndGet();
                                }
                                else
                                {
                                	MailStat.SEND_SUCCESS_NUM_2.incrementAndGet();
                                }
                            }
                    	}
                    	catch (InterruptedException inupte)
                    	{
                    		MailStat.SEND_FAILED_NUM_2.incrementAndGet();
                    		//当有线程挂起的时候，停止所有线程，在装箱操作的时候在启动所有线程
                    		MailService.getInstance().setRunning(false);
                    	}
                    	catch (Exception e)
                    	{
                    		MailStat.SEND_FAILED_NUM_2.incrementAndGet();
                    		//全局捕获
                    		e.printStackTrace();
                    	}
                    }
                }
            };
            
            t.start();
        }
    }
    
    public void setRunning(boolean r)
    {
    	running.set(r);
    }
    
    public boolean getRunning()
    {
    	return running.get();
    }
    
    public static MailService getInstance()
    {
    	return _instance;
    }
    
    private static MailService _instance = new MailService();
    
    private MailService()
    {
    }
    
}